package cn.cqautotest.cqviehelper.ui.fragment;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.CalendarContract;
import android.util.ArrayMap;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.RequiresApi;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.ConcatAdapter;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.blankj.utilcode.util.ToastUtils;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.haibin.calendarview.Calendar;
import com.haibin.calendarview.CalendarLayout;
import com.haibin.calendarview.CalendarView;
import com.zhuangfei.timetable.model.Schedule;

import java.time.DayOfWeek;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.WeekFields;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import cn.cqautotest.cqviehelper.R;
import cn.cqautotest.cqviehelper.adapters.ItineraryAdapter;
import cn.cqautotest.cqviehelper.base.BaseActivity;
import cn.cqautotest.cqviehelper.base.BaseFragment;
import cn.cqautotest.cqviehelper.config.Constants;
import cn.cqautotest.cqviehelper.interfaces.IAppDataCallback;
import cn.cqautotest.cqviehelper.presenter.CoursePresenter;
import cn.cqautotest.cqviehelper.presenter.UpdateAppDataPresenter;
import cn.cqautotest.cqviehelper.ui.activity.HomeActivity;
import cn.cqautotest.cqviehelper.utils.AssetUtils;
import cn.cqautotest.cqviehelper.utils.MyScheduleSupport;
import cn.cqautotest.cqviehelper.utils.StringJoinUtils;
import cn.cqautotest.cqviehelper.views.MarqueeTextView;

@SuppressLint("NonConstantResourceId")
@RequiresApi(api = Build.VERSION_CODES.O)
public class SchoolCalendarFragment extends BaseFragment<BaseActivity> implements CalendarView.OnCalendarSelectListener, CalendarView.OnYearChangeListener, IAppDataCallback {

    @BindView(R.id.tv_month_day)
    TextView mTextMonthDay;
    @BindView(R.id.tv_year)
    TextView mTextYear;
    @BindView(R.id.tv_lunar)
    TextView mTextLunar;
    @BindView(R.id.tvPost)
    MarqueeTextView tvPost;
    @BindView(R.id.rl_tool)
    RelativeLayout mRelativeTool;
    @BindView(R.id.tv_current_day)
    TextView mTextCurrentDay;
    @BindView(R.id.calendarView)
    CalendarView mCalendarView;
    @BindView(R.id.calendarLayout)
    CalendarLayout mCalendarLayout;
    @BindView(R.id.tvWeekDescription)
    TextView mTvWeekDescription;
    @BindView(R.id.fab_add_schema)
    FloatingActionButton mFabAddSchemaView;
    @BindView(R.id.fl_current)
    View mFlCurrent;
    private int mYear;
    @BindView(R.id.tvFestivalInfoTitle)
    TextView mTvFestivalInfoTitle;
    @BindView(R.id.rvItemDetail)
    RecyclerView mRvItemDetail;
    private UpdateAppDataPresenter mUpdateAppDataPresenter;
    private ItineraryAdapter mItineraryAdapter;
    private CoursePresenter mCoursePresenter;

    public static SchoolCalendarFragment getInstance() {
        return new SchoolCalendarFragment();
    }

    @Override
    protected int getLayoutResId() {
        return R.layout.fragment_school_calendar;
    }

    @Override
    protected void initPresenter() {
        mUpdateAppDataPresenter = UpdateAppDataPresenter.getInstance();
        mUpdateAppDataPresenter.registered(this);
        mUpdateAppDataPresenter.updateSchoolCalendar();
        mUpdateAppDataPresenter.updatePostContent();
        mCoursePresenter = CoursePresenter.getInstance();
    }

    @Override
    protected void initView(View rootView) {
        mTextYear.setText(String.valueOf(mCalendarView.getCurYear()));
        mTextMonthDay.setText(String.format("%s月%s日", mCalendarView.getCurMonth(), mCalendarView.getCurDay()));
        mTextLunar.setText(mCalendarView.getSelectedCalendar().getLunar());
        mTextCurrentDay.setText("今");
        LinearLayoutManager layoutManager = new LinearLayoutManager(getAttachActivity());
        mRvItemDetail.setLayoutManager(layoutManager);
        mItineraryAdapter = new ItineraryAdapter();
        ConcatAdapter concatAdapter = new ConcatAdapter(mItineraryAdapter);
        mRvItemDetail.setAdapter(concatAdapter);
    }

    @Override
    protected void initData() {
        mYear = mCalendarView.getCurYear();
        Map<String, Calendar> map = AssetUtils.parseSchoolCalendar(mContext, R.raw.school_calendar);
        //此方法在巨大的数据量上不影响遍历性能，推荐使用
        mCalendarView.setSchemeDate(map);
        setFestivalInfo();
    }

    @Override
    protected void initEvent() {
        mTextMonthDay.setOnClickListener(v -> {
            //如果不为展开状态，则展开
            if (!mCalendarLayout.isExpand()) {
                mCalendarLayout.expand();
                return;
            }
            mCalendarView.showYearSelectLayout(mYear);
            mTextLunar.setVisibility(View.GONE);
            mTextYear.setVisibility(View.GONE);
            mTextMonthDay.setText(String.valueOf(mYear));
        });
        //滚动到当前天
        mFlCurrent.setOnClickListener(v -> {
            //如果年视图为展开状态，则收起来
            if (mCalendarView.isYearSelectLayoutVisible()) {
                mCalendarView.closeYearSelectLayout();
            }
            mCalendarView.scrollToCurrent();
            mTextMonthDay.setText(String.format("%s月%s日", mCalendarView.getCurMonth(), mCalendarView.getCurDay()));
        });
        //设置日期选择事件的监听
        mCalendarView.setOnCalendarSelectListener(this);
        //设置年份改变的监听
        mCalendarView.setOnYearChangeListener(this);
        mCalendarView.setOnCalendarLongClickListener(new CalendarView.OnCalendarLongClickListener() {
            @Override
            public void onCalendarLongClickOutOfRange(Calendar calendar) {

            }

            @Override
            public void onCalendarLongClick(Calendar calendar) {
                try {
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.addCategory(Intent.CATEGORY_DEFAULT);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    String uri = StringJoinUtils.join(CalendarContract.CONTENT_URI.toString(), "/time/", calendar.getTimeInMillis());
                    intent.setData(Uri.parse(uri));
                    startActivity(intent);
                } catch (Exception e) {
                    e.printStackTrace();
                    ToastUtils.showShort("暂未适配您的机型，如果想要添加日历提醒，请手动添加");
                }
            }
        });
        mFabAddSchemaView.setOnClickListener(v -> {
            //跳转至系统日历添加日历事件页面
            Intent intent = new Intent(Intent.ACTION_INSERT);
            intent.setData(CalendarContract.Events.CONTENT_URI);
            startActivity(intent);
        });
        //mItineraryAdapter.setOnItemLongClickListener(schedule -> startActivity(FileManagerActivity.class));
    }

    @Override
    protected void release() {
        if (mUpdateAppDataPresenter != null) mUpdateAppDataPresenter.unRegistered(this);
    }

    /**
     * 超出范围越界
     *
     * @param calendar 日历对象
     */
    @Override
    public void onCalendarOutOfRange(Calendar calendar) {

    }

    /**
     * 日期选择事件
     *
     * @param calendar 日历对象
     * @param isClick
     */
    @Override
    public void onCalendarSelect(Calendar calendar, boolean isClick) {
        mTextLunar.setVisibility(View.VISIBLE);
        mTextYear.setVisibility(View.VISIBLE);
        mTextMonthDay.setText(String.format("%s月%s日", calendar.getMonth(), calendar.getDay()));
        mTextYear.setText(String.valueOf(calendar.getYear()));
        mTextLunar.setText(calendar.getLunar());
        mYear = calendar.getYear();
        String weekDescription = getStringArray(R.array.chinese_week_string_array)[calendar.getWeek()];
        mTvWeekDescription.setText(weekDescription);
        setFestivalInfo();
    }

    /**
     * 设置选中天的课程信息
     */
    private void setFestivalInfo() {
        Calendar selectedCalendar = mCalendarView.getSelectedCalendar();
        long defaultTimeMills = System.currentTimeMillis();
        long termStartTimestamp = mSpUserInfoSetting.getLong(Constants.START_DATE, defaultTimeMills);
        int week = selectedCalendar.getWeek();
        if (week == 0) {
            week = 7;
        }
        //当前选中日期在一年中所在的周次减去开学日期在一年中的所在的周次就是当前第几周
        LocalDateTime startLocalTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(termStartTimestamp), ZoneId.systemDefault());
        LocalDateTime endLocalTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(selectedCalendar.getTimeInMillis()), ZoneId.systemDefault());
        WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 1);
        int startDayOfWeek = startLocalTime.get(weekFields.weekOfYear());
        int endDayOfWeek = endLocalTime.get(weekFields.weekOfYear());
        int calcCurrentWeek = endDayOfWeek - startDayOfWeek + 1;
        //Log.d(TAG, "setFestivalInfo: =====> currentWeek is " + currentWeek);
        List<Schedule> haveSubjectsWithDay = MyScheduleSupport.getHaveSubjectsWithDay(mCoursePresenter.deduplication(), calcCurrentWeek, week - 1);
        if (haveSubjectsWithDay.size() == 0) {
            Schedule schedule = new Schedule();
            ArrayMap<String, Object> extras = new ArrayMap<>();
            extras.put(Constants.HAVE_COURSE, false);
            schedule.setExtras(extras);
            haveSubjectsWithDay.add(schedule);
        }
        mItineraryAdapter.setObjects(haveSubjectsWithDay);
    }

    /**
     * 年份改变事件
     *
     * @param year 年份
     */
    @Override
    public void onYearChange(int year) {
        mTextMonthDay.setText(String.valueOf(year));
    }

    /**
     * 在界面重新可见的时候更改页面的主题
     */
    @Override
    protected void uiReShowing() {
        setFestivalInfo();
        FragmentActivity activity = getActivity();
        if (activity instanceof HomeActivity) {
            HomeActivity homeActivity = (HomeActivity) activity;
            homeActivity.resetBgState();
        }
        long termStartTimestamp = mSpUserInfoSetting.getLong(Constants.START_DATE, System.currentTimeMillis());
        int currentWeek = MyScheduleSupport.timeTransform(termStartTimestamp);
        if (currentWeek < 1) {
            mTvFestivalInfoTitle.setText("课程表 | 尚未开学");
        } else {
            mTvFestivalInfoTitle.setText(String.format("课程表 | 第%s周", currentWeek));
        }
    }

    @Override
    public void onSidebarTimeUpdate(String[] times) {

    }

    @Override
    public void onSchoolCalendarUpdate(Map<String, Calendar> calendarMap) {
        if (mCalendarView != null) {
            mCalendarView.setSchemeDate(calendarMap);
        }
    }

    @Override
    public void onPostContentUpdate(String postContent) {
        if (tvPost != null) {
            tvPost.setText(postContent);
        }
    }
}
